__author__ = 'Brandon Corfman'
from actions import Action

class Path(Action):
    def __init__(self, enter, exit):
        """
        enter: a string describing the tunnel entrances -- compass directions (NSEW)
        exit: a string describing the tunnel exits -- compass directions (NSEW)
        reveal: indicates whether the square is displayed on the map
        """
        self.enter = enter
        self.exit = exit
        self.reveal = False
        self.state = None
        self.row = None
        self.col = None

    def __repr__(self):
        """
        Outputs unicode characters that show the tunnel paths.
        Almost the same as __str__ except for the representation of
        tunnel dead ends.
        """
        u = '?'
        if self.enter == 'SEW' and self.exit == 'SEW':
            u = chr(0x252C)
        elif self.enter == 'NSEW' and self.exit == 'NSEW':
            u = chr(0x253C)
        elif self.enter == 'EW' and self.exit == 'EW':
            u = chr(0x2500)
        elif self.enter == 'NS' and self.exit == 'NS':
            u = chr(0x2502)
        elif self.enter == 'NEW' and self.exit == 'NEW':
            u = chr(0x2534)
        elif self.enter == 'NSE' and self.exit == 'NSE':
            u = chr(0x251C)
        elif self.enter == 'NSW' and self.exit == 'NSW':
            u = chr(0x2524)
        elif self.enter == 'SW' and self.exit == 'SW':
            u = chr(0x2510)
        elif self.enter == 'NW' and self.exit == 'NW':
            u = chr(0x2518)
        elif self.enter == 'SE' and self.exit == 'SE':
            u = chr(0x250C)
        elif self.enter == 'NE' and self.exit == 'NE':
            u = chr(0x2514)
        elif self.enter != self.exit: # dead end
            u = 'D'
        return u

    def __str__(self):
        """
        Outputs unicode characters that show the tunnel paths.
        """
        u = '?'
        if self.enter == 'SEW' and self.exit == 'SEW':
            u = chr(0x252C)
        elif self.enter == 'NSEW' and self.exit == 'NSEW':
            u = chr(0x253C)
        elif self.enter == 'EW' and self.exit == 'EW':
            u = chr(0x2500)
        elif self.enter == 'NS' and self.exit == 'NS':
            u = chr(0x2502)
        elif self.enter == 'NEW' and self.exit == 'NEW':
            u = chr(0x2534)
        elif self.enter == 'NSE' and self.exit == 'NSE':
            u = chr(0x251C)
        elif self.enter == 'NSW' and self.exit == 'NSW':
            u = chr(0x2524)
        elif self.enter == 'SW' and self.exit == 'SW':
            u = chr(0x2510)
        elif self.enter == 'NW' and self.exit == 'NW':
            u = chr(0x2518)
        elif self.enter == 'SE' and self.exit == 'SE':
            u = chr(0x250C)
        elif self.enter == 'NE' and self.exit == 'NE':
            u = chr(0x2514)
        elif self.enter != self.exit: # dead end
            u = 'Dead end {0}'.format(self.enter)
        return u

    def spin(self):
        """
        Creates a new Path card that is spun 180 degrees from the existing Path card and returns it.
        """
        if self.enter == 'SEW' and self.exit == 'SEW':
            self.enter = self.exit = 'NEW'
        elif self.enter == 'NEW' and self.exit == 'NEW':
            self.enter = self.exit = 'SEW'
        elif self.enter == 'NSE' and self.exit == 'NSE':
            self.enter = self.exit = 'NSW'
        elif self.enter == 'NSW' and self.exit == 'NSW':
            self.enter = self.exit = 'NSE'
        elif self.enter == 'SW' and self.exit == 'SW':
            self.enter = self.exit = 'NE'
        elif self.enter == 'NE' and self.exit == 'NE':
            self.enter = self.exit = 'SW'
        elif self.enter == 'NW' and self.exit == 'NW':
            self.enter = self.exit = 'SE'
        elif self.enter == 'SE' and self.exit == 'SE':
            self.enter = self.exit = 'NW'

    def precondition(self, agent, board, others):
        """
        The conditions that must be true before the execute method can be called.
        """
        if agent.states:
            print("Sorry, you cannot lay a new path when you have a broken tool.")
            return 0.0
        rank, self.row, self.col = agent.decide_path_card(board, self)
        return rank

    def execute(self, agent, board, others):
        """
        Places the path on the board.
        The correct orientation state is maintained from the precondition method.
        """
        agent.notify('SetPath {0} {1} {2} {3}'.format(agent.parent.name, self.row,
                                                      self.col, repr(self)))
        board.set_path(agent, self.row, self.col, self)

    def is_flippable(self):
        return ((self.enter == 'SEW' and self.exit == 'SEW') or
                (self.enter == 'NEW' and self.exit == 'NEW') or
                (self.enter == 'NSE' and self.exit == 'NSE') or
                (self.enter == 'NSW' and self.exit == 'NSW') or
                (self.enter == 'SW' and self.exit == 'SW') or
                (self.enter == 'NE' and self.exit == 'NE') or
                (self.enter == 'NW' and self.exit == 'NW') or
                (self.enter == 'SE' and self.exit == 'SE'))

class Ladder(Path):
    def __init__(self):
        super(Ladder, self).__init__('NSEW', 'NSEW')

    def __repr__(self):
        return chr(0x253C)

    def is_flippable(self):
        return False

class Goal(Path):
    def __init__(self, enter, state):
        super(Goal, self).__init__(enter, enter)
        self.reveal = False
        self.state = state

    def __repr__(self):
        u = '?'
        if self.state == 'gold' and self.reveal:
            u = 'G'
        elif self.state == 'stone' and self.reveal:
            u = 'S'
        return u

    def is_flippable(self):
        return False